package cn.stylefeng.mferp.modular.business.controller;

import cn.hutool.core.util.NumberUtil;
import cn.stylefeng.mferp.core.log.LogObjectHolder;
import cn.stylefeng.mferp.core.util.DateUtil;
import cn.stylefeng.mferp.core.util.ReflectUtil;
import cn.stylefeng.mferp.modular.business.constant.Constants;
import cn.stylefeng.mferp.modular.business.model.*;
import cn.stylefeng.mferp.modular.business.service.ITrwdService;
import cn.stylefeng.mferp.modular.business.warpper.TrwdWarpper;
import cn.stylefeng.mferp.modular.dispatch.model.TRwdSaveModel;
import cn.stylefeng.mferp.modular.dispatch.service.ITRwdService;
import cn.stylefeng.roses.core.base.controller.BaseController;
import cn.stylefeng.roses.core.reqres.response.ErrorResponseData;
import cn.stylefeng.roses.core.reqres.response.ResponseData;
import cn.stylefeng.roses.core.reqres.response.SuccessResponseData;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.Exception;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicReference;

import static cn.stylefeng.roses.core.reqres.response.ResponseData.DEFAULT_SUCCESS_CODE;

/**
 * 任务单控制器
 *
 * @author fengshuonan
 * @Date 2020-05-27 23:25:57
 */
@Controller
@RequestMapping("/trwd")
public class TrwdController extends BaseController {
    private static Logger logger = LoggerFactory.getLogger(TrwdController.class);
    private String PREFIX = "/business/trwd/";

    @Autowired
    private ITrwdService trwdService;

    @Autowired
    private ITRwdService itRwdService;

    @Value("${yzr.excel.file_name}")
    private String fileName;

    /**
     * 跳转到任务单首页
     */
    @RequestMapping("")
    public String index() {
        return PREFIX + "trwd.html";
    }

    @RequestMapping("/trwd_sgpb/{rwdh}")
    public String sgpb(@PathVariable(name = "rwdh") String rwdh, Model model) {
        Trwd trwd = trwdService.selectByRwdh(rwdh);
        model.addAttribute("item",trwd);
        LogObjectHolder.me().set(trwd);
        return PREFIX + "trwd_sgpb.html";
    }

    @RequestMapping("/trwd_sgpb")
    public String sgpbPage(Model model) {
        model.addAttribute("item", new Trwd());
        return PREFIX + "trwd_sgpb.html";
    }

    /**
     * 跳转到资料室任务单管理
     */
    @RequestMapping("/zl")
    public String zlRwdPage() {
        return PREFIX + "trwd_zl.html";
    }

    /**
     * 跳转到添加任务单
     */
    @RequestMapping("/trwd_add")
    public String trwdAdd() {
        return PREFIX + "trwd_add.html";
    }

    /**
     * 跳转到修改任务单
     */
    @RequestMapping("/trwd_update/{trwdId}")
    public String trwdUpdate(@PathVariable Integer trwdId, Model model) {
        Trwd trwd = trwdService.selectByRwdh(String.valueOf(trwdId));
        model.addAttribute("item",trwd);
        LogObjectHolder.me().set(trwd);
        return PREFIX + "trwd_edit.html";
    }

    /**
     * 识别任务
     */
    @RequestMapping("/trwd_sb")
    public String trwdSb() {
        return PREFIX + "trwd_sb.html";
    }

    /**
     * 获取任务单列表
     */
    @RequestMapping(value = "/list")
    @ResponseBody
    public Object list(@RequestParam(required = false) String beginTime,
                       @RequestParam(required = false) String endTime,
                       @RequestParam(required = false) String gcmc,
                       @RequestParam(required = false) String rwdh,
                       @RequestParam(required = false) String scbt,
                       @RequestParam(required = false) String zt) {
        List<Map<String, Object>> trwds = trwdService.selectTrwds(beginTime, endTime, gcmc, rwdh, scbt, zt);
        return new TrwdWarpper(trwds).wrap();
    }

    /**
     * 新增任务单
     */
    @RequestMapping(value = "/add")
    @ResponseBody
    public Object add(Trwd trwd) {
        trwdService.insert(trwd);
        return SUCCESS_TIP;
    }

    /**
     * 删除任务单
     */
    @RequestMapping(value = "/delete")
    @ResponseBody
    public Object delete(@RequestParam Integer trwdId) {
        trwdService.deleteById(trwdId);
        return SUCCESS_TIP;
    }

    /**
     * 修改任务单
     */
    @RequestMapping(value = "/update")
    @ResponseBody
    public Object update(Trwd trwd) {
        trwdService.updateById(trwd);
        return SUCCESS_TIP;
    }

    /**
     * 任务单详情
     */
    @RequestMapping(value = "/detail/{trwdId}")
    @ResponseBody
    public Object detail(@PathVariable("trwdId") Integer trwdId) {
        return trwdService.selectById(trwdId);
    }

    @RequestMapping(value = "/get_by_rwd/{rwdh}")
    @ResponseBody
    public Object getAllByRwdh(@PathVariable("rwdh") String rwdh) {
        return trwdService.selectByRwdh(rwdh);
    }

    /**
     * 批量调整掺量
     */
    @RequestMapping(value = "/batch_modify_cl")
    @ResponseBody
    public Object batchModifyCl(@RequestParam String scbt, @RequestParam double cl) {
        logger.info("batchModifyCl scbt:{}, cl:{}", scbt, cl);
        if(StringUtils.isBlank(scbt) || "*".equals(scbt) || "0".equals(scbt)) {
            return new ErrorResponseData(400, "请选择生产线");
        }
        List<Trwd> list = trwdService.selectCheckRwdByScbt(scbt);
        if(list == null || list.isEmpty()) {
            return new ErrorResponseData(400, "该生产线不存在需调整的任务单");
        }
        for(Trwd trwd : list) {
            trwdService.adjustCl(trwd, scbt, cl);
            trwdService.addPhbLog(trwd, scbt);
        }
        return SUCCESS_TIP;
    }

    /**
     * 选单调整掺量
     */
    @RequestMapping(value = "/choose_to_modify_cl")
    @ResponseBody
    public Object chooseToModifyCl(@RequestParam(name = "rwdhs[]") List<String> rwdhs, @RequestParam String scbt, @RequestParam double cl) {
        logger.info("chooseToModifyCl rwdhs:{}, scbt:{}, cl:{}", rwdhs.toString(), scbt, cl);
        if(StringUtils.isBlank(scbt) || "*".equals(scbt) || "0".equals(scbt)) {
            return new ErrorResponseData(400, "请选择生产线");
        }
        if(rwdhs.isEmpty()) {
            return new ErrorResponseData(400, "请选择任务单");
        }
        List<Trwd> list = trwdService.selectCheckRwdByRwdhs(rwdhs);
        if(list == null || list.isEmpty()) {
            return new ErrorResponseData(400, "该生产线不存在需调整的任务单");
        }
        for(Trwd trwd : list) {
            trwdService.adjustCl(trwd, scbt, cl);
            trwdService.addPhbLog(trwd, scbt);
        }
        return SUCCESS_TIP;
    }

    /**
     * 选单调整砂率
     */
    @RequestMapping(value = "/choose_to_modify_sl")
    @ResponseBody
    public Object chooseToModifySl(@RequestParam(name = "rwdhs[]") List<String> rwdhs, @RequestParam String scbt, @RequestParam double sl) {
        logger.info("chooseToModifySl rwdhs:{}, scbt:{}, sl:{}", rwdhs.toString(), scbt, sl);
        if(StringUtils.isBlank(scbt) || "*".equals(scbt) || "0".equals(scbt)) {
            return new ErrorResponseData(400, "请选择生产线");
        }
        if(rwdhs.isEmpty()) {
            return new ErrorResponseData(400, "请选择任务单");
        }
        List<Trwd> list = trwdService.selectCheckRwdByRwdhs(rwdhs);
        if(list == null || list.isEmpty()) {
            return new ErrorResponseData(400, "该生产线不存在需调整的任务单");
        }
        for(Trwd trwd : list) {
            trwdService.adjustSl(trwd, scbt, sl);
            trwdService.addPhbLog(trwd, scbt);
        }
        return SUCCESS_TIP;
    }


    /**
     * 选单选线调整容重
     */
    @RequestMapping(value = "/choose_to_modify_rz_one_scbt")
    @ResponseBody
    public Object chooseToModifyRzOneScbt(@RequestParam(name = "rwdhs[]") List<String> rwdhs, @RequestParam String scbt, @RequestParam double rzbl) {
        logger.info("chooseToModifyRzOneScbt rwdhs:{}, scbt:{}, rzbl:{}", rwdhs.toString(), scbt, rzbl);
        if(StringUtils.isBlank(scbt) || "*".equals(scbt) || "0".equals(scbt)) {
            return new ErrorResponseData(400, "请选择生产线");
        }
        if(new BigDecimal(rzbl).subtract(BigDecimal.valueOf(Double.parseDouble("0.99"))).compareTo(BigDecimal.ZERO) < 0 ||
            new BigDecimal(rzbl).subtract(BigDecimal.valueOf(Double.parseDouble("1.05"))).compareTo(BigDecimal.ZERO) > 0) {
            return new ErrorResponseData(400, "容重比例必须在0.99与1.05之间");
        }
        if(rwdhs.isEmpty()) {
            return new ErrorResponseData(400, "请选择任务单");
        }
        List<Trwd> list = trwdService.selectCheckRwdByRwdhs(rwdhs);
        if(list == null || list.isEmpty()) {
            return new ErrorResponseData(400, "该生产线不存在需调整的任务单");
        }
        for(Trwd trwd : list) {
            List<TrwdphbyclModel> trwdphbyclModels = trwdService.adjustRz(trwd, scbt, rzbl);
            if(trwdphbyclModels != null) {
                String ftpz = trwd.getFtpz();
                String strength = ftpz.substring(0, 3);
                boolean result =  trwdService.checkBulkDensity(trwdphbyclModels, strength);
                if(result) {
                    trwdService.updateTrwdphbycls(trwdphbyclModels);
                    trwdService.addPhbLogForAdjustRz(trwd, scbt);
                }
            }
        }
        return SUCCESS_TIP;
    }

    /**
     * 选单选线容重回退
     */
    @RequestMapping(value = "/choose_to_rz_back_one_scbt")
    @ResponseBody
    public Object chooseToRzBackOneScbt(@RequestParam(name = "rwdhs[]") List<String> rwdhs, @RequestParam String scbt) {
        logger.info("chooseToRzBackOneScbt rwdhs:{}, scbt:{}", rwdhs.toString(), scbt);
        if(StringUtils.isBlank(scbt) || "*".equals(scbt) || "0".equals(scbt)) {
            return new ErrorResponseData(400, "请选择生产线");
        }
        if(rwdhs.isEmpty()) {
            return new ErrorResponseData(400, "请选择任务单");
        }
        List<Trwd> list = trwdService.selectCheckRwdByRwdhs(rwdhs);
        if(list == null || list.isEmpty()) {
            return new ErrorResponseData(400, "该生产线不存在指定的任务单");
        }
        List<String> successList = new ArrayList<>();
        for(Trwd trwd : list) {
            if(trwdService.rzBack(trwd, scbt)) {
                successList.add(trwd.getFrwdh().toString());
            }
        }
        if(!successList.isEmpty()) {
            StringBuilder temp = new StringBuilder();
            for (String rwdh : successList) {
                temp.append(rwdh+" ");
            }
            return new ResponseData(true, DEFAULT_SUCCESS_CODE, temp.toString() + "容重回退成功", successList);
        }
        return new ErrorResponseData(400, "选单选线容重回退失败");
    }

    /**
     * 选单调整容重
     */
    @RequestMapping(value = "/choose_to_modify_rz_all_scbt")
    @ResponseBody
    public Object chooseToModifyRzAllScbt(@RequestParam(name = "rwdhs[]") List<String> rwdhs, @RequestParam double rzbl) {
        logger.info("chooseToModifyRzAllScbt rwdhs:{}, rzbl:{}", rwdhs.toString(), rzbl);
        String[] arr = new String[]{"1", "2", "3", "5", "6"};
        if(new BigDecimal(rzbl).subtract(BigDecimal.valueOf(Double.parseDouble("0.99"))).compareTo(BigDecimal.ZERO) < 0 ||
                new BigDecimal(rzbl).subtract(BigDecimal.valueOf(Double.parseDouble("1.05"))).compareTo(BigDecimal.ZERO) > 0) {
            return new ErrorResponseData(400, "容重比例必须在0.99与1.05之间");
        }
        if(rwdhs.isEmpty()) {
            return new ErrorResponseData(400, "请选择任务单");
        }
        List<Trwd> list = trwdService.selectCheckRwdByRwdhs(rwdhs);
        if(list == null || list.isEmpty()) {
            return new ErrorResponseData(400, "该生产线不存在需调整的任务单");
        }
        for(Trwd trwd : list) {
            for(String scbt : arr) {
                List<TrwdphbyclModel> trwdphbyclModels = trwdService.adjustRz(trwd, scbt, rzbl);
                if (trwdphbyclModels != null) {
                    String ftpz = trwd.getFtpz();
                    String strength = ftpz.substring(0, 3);
                    boolean result = trwdService.checkBulkDensity(trwdphbyclModels, strength);
                    if (result) {
                        trwdService.updateTrwdphbycls(trwdphbyclModels);
                        trwdService.addPhbLogForAdjustRz(trwd, scbt);
                    }
                }
            }
        }
        return SUCCESS_TIP;
    }

    /**
     * 选单容重回退
     */
    @RequestMapping(value = "/choose_to_rz_back_all_scbt")
    @ResponseBody
    public Object chooseToRzBackAllScbt(@RequestParam(name = "rwdhs[]") List<String> rwdhs) {
        logger.info("chooseToRzBackAllScbt rwdhs:{}", rwdhs.toString());
        String[] arr = new String[]{"1", "2", "3", "5", "6"};
        if(rwdhs.isEmpty()) {
            return new ErrorResponseData(400, "请选择任务单");
        }
        List<Trwd> list = trwdService.selectCheckRwdByRwdhs(rwdhs);
        if(list == null || list.isEmpty()) {
            return new ErrorResponseData(400, "该生产线不存在需调整的任务单");
        }
        List<String> successList = new ArrayList<>();
        for(Trwd trwd : list) {
            int successCount = 0;
            for(String scbt : arr) {
                if(trwdService.rzBack(trwd, scbt)) {
                    successCount++;
                }
            }
            if(successCount > 0) {
                successList.add(trwd.getFrwdh().toString());
            }
        }
        if(!successList.isEmpty()) {
            StringBuilder temp = new StringBuilder();
            for (String rwdh : successList) {
                temp.append(rwdh+" ");
            }
            return new ResponseData(true, DEFAULT_SUCCESS_CODE, temp.toString() + "容重回退成功", successList);
        }
        return new ErrorResponseData(400, "选单容重回退失败");
    }

    /**
     * 选单调砂
     */
    @RequestMapping(value = "/choose_to_modify_sand")
    @ResponseBody
    public Object chooseToModifySand(@RequestParam(name = "rwdhs[]") List<String> rwdhs, @RequestParam String scbt,
                                     @RequestParam double sand, @RequestParam String sandClass) {
        logger.info("chooseToModifySand rwdhs:{}, scbt:{}", rwdhs.toString(), scbt);
        logger.info("chooseToModifySand sand:{}, sandClass:{}", sand, sandClass);
        if(StringUtils.isBlank(scbt) || "*".equals(scbt) || "0".equals(scbt)) {
            return new ErrorResponseData(400, "请选择生产线");
        }
        if(StringUtils.isBlank(sandClass)) {
            return new ErrorResponseData(400, "请选择砂品种");
        }
        if(rwdhs.isEmpty()) {
            return new ErrorResponseData(400, "请选择任务单");
        }
        List<Trwd> list = trwdService.selectCheckRwdByRwdhs(rwdhs);
        if(list == null || list.isEmpty()) {
            return new ErrorResponseData(400, "该生产线不存在需调整的任务单");
        }
        for(Trwd trwd : list) {
            trwdService.adjustSand(trwd, scbt, sand, sandClass);
            trwdService.addPhbLog(trwd, scbt);
        }
        return SUCCESS_TIP;
    }

    /**
     * 选单调石
     */
    @RequestMapping(value = "/choose_to_modify_stone")
    @ResponseBody
    public Object chooseToModifyStone(@RequestParam(name = "rwdhs[]") List<String> rwdhs, @RequestParam String scbt,
                                     @RequestParam double stone, @RequestParam String stoneClass) {
        logger.info("chooseToModifyStone rwdhs:{}, scbt:{}", rwdhs.toString(), scbt);
        logger.info("chooseToModifyStone stone:{}, stoneClass:{}", stone, stoneClass);
        if(StringUtils.isBlank(scbt) || "*".equals(scbt) || "0".equals(scbt)) {
            return new ErrorResponseData(400, "请选择生产线");
        }
        if(StringUtils.isBlank(stoneClass)) {
            return new ErrorResponseData(400, "请选择碎石品种");
        }
        if(rwdhs.isEmpty()) {
            return new ErrorResponseData(400, "请选择任务单");
        }
        List<Trwd> list = trwdService.selectCheckRwdByRwdhs(rwdhs);
        if(list == null || list.isEmpty()) {
            return new ErrorResponseData(400, "该生产线不存在需调整的任务单");
        }
        for(Trwd trwd : list) {
            trwdService.adjustStone(trwd, scbt, stone, stoneClass);
            trwdService.addPhbLog(trwd, scbt);
        }
        return SUCCESS_TIP;
    }

    /**
     * 单个配合比原材料信息保存配方
     */
    @RequestMapping(value = "/save_recipe")
    @ResponseBody
    public Object saveRecipe(@RequestBody TRecipeModel data) {
        logger.info("saveRecipe data:{}", data.toString());
        List<TrwdphbyclModel> list= data.getData();
        String ftpz = data.getFtpz();
        if(list != null && !list.isEmpty() && StringUtils.isNotBlank(ftpz) && ftpz.length() >= 3) {
            String strength = ftpz.substring(0, 3);
            boolean checkBulkDensity = trwdService.checkBulkDensity(list, strength);
            if(!checkBulkDensity) {
                String message = "强度等级" + strength + Constants.BUSINESS_BULK_DENSITY_STANDARD_DENSITY_IS_OVER;
                return new ErrorResponseData(ResponseData.DEFAULT_ERROR_CODE, message, null);
            }
        }
        return trwdService.saveRecipe(data);
    }

    /**
     * 获取指定施工配比
     */
    @RequestMapping(value = "/get_sgpb_recipe")
    @ResponseBody
    public Object getSgpbRecipe(@RequestParam String rwdh, @RequestParam String scbt, @RequestParam String sgpb) {
        logger.info("useSgpbRecipe sgpb:{}, rwdh:{}, scbt:{}", sgpb, rwdh, scbt);
        List<TrwdphbyclModel> list = trwdService.getSgpbRecipe(sgpb);
        if(list != null && !list.isEmpty()) {
            for (TrwdphbyclModel model : list) {
                model.setFrwdh(Integer.valueOf(rwdh));
                model.setFpblb(0);
                model.setFbtid(Integer.valueOf(scbt));
            }
        }
        return new SuccessResponseData(list);
    }

    /**
     * 对外生产记录导出文件下载（失败了会返回一个有部分数据的Excel）
     * <p>1. 创建excel对应的实体对象
     * <p>2. 设置返回的 参数
     * <p>3. 直接写，这里注意，finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大
     */
    @GetMapping("/download_out")
    public void downloadOut(HttpServletResponse response,
                            @RequestParam(required = false) String beginTime,
                            @RequestParam(required = false) String endTime,
                            @RequestParam(required = false) String zt,
                            @RequestParam(required = false) String gcmc,
                            @RequestParam(required = false) String scbt,
                            @RequestParam(required = false) String rwdh,
                            @RequestParam(required = false) String excelType) throws IOException {
        List<Trwd> trwds = trwdService.selectTrwdListOut(beginTime, endTime, zt, gcmc, scbt, rwdh);
        List<TrwdModel> trwdModels = new ArrayList<>();
        for (Trwd trwd: trwds) {
            TrwdModel trwdModel = new TrwdModel();
            ReflectUtil.copyValue(trwd, trwdModel);
            trwdModels.add(trwdModel);
        }
        String thisFileName;
        ExcelWriter excelWriter;
        if(StringUtils.isNotBlank(excelType) && "03".equals(excelType)) {
            thisFileName = "任务单" + System.currentTimeMillis() + ExcelTypeEnum.XLS.getValue();
            excelWriter = EasyExcel.write(response.getOutputStream()).excelType(ExcelTypeEnum.XLS).build();
        } else {
            thisFileName = "任务单" + System.currentTimeMillis() + ExcelTypeEnum.XLSX.getValue();
            excelWriter = EasyExcel.write(response.getOutputStream()).excelType(ExcelTypeEnum.XLSX).build();
        }
        if(StringUtils.isNotBlank(thisFileName) && excelWriter != null && !trwdModels.isEmpty()) {
            try {
                // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
                response.setContentType("application/vnd.ms-excel");
                response.setCharacterEncoding("utf-8");
                // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
                String fileName = URLEncoder.encode(thisFileName, "UTF-8");
                response.setHeader("Content-disposition", "attachment;filename=" + fileName);
                WriteSheet writeSheet1 = EasyExcel.writerSheet(0, "外部任务单").head(TrwdModel.class).build();
                excelWriter.write(trwdModels, writeSheet1);
                excelWriter.finish();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("导出外部任务单出错", e);
            }
        }
    }

    @RequestMapping(value = "/sb_content")
    @ResponseBody
    public Object sbContent(@RequestParam String content) {
        return itRwdService.analyseContent(content);
    }

    @RequestMapping(value = "/save_trwd")
    @ResponseBody
    public Object saveTrwd(@RequestBody TRwdSaveModel data) {
        return itRwdService.saveTRwd(data);
    }

}
